﻿#region

using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using Vin.Tool.Core.JsonCategory.Converters;

#endregion

namespace Vin.Tool.Core.JsonCategory;

public class JsonTool
{
    /// <summary>
    /// 自定义转换器
    /// </summary>
    private static List<JsonConverter> _customConverters = new List<JsonConverter>
    {
        // 时间格式化
        new DateTimeConverter(),
        // new DateTimeNullConverter(),
        // long转string
        new LongToStringConverter(),
    };
    
    public static void AddCustomConverter(JsonConverter? converter)
    {
        if (converter == null) return;
        if (_customConverters.Contains(converter)) return;
        _customConverters.Add(converter);
    }
    
    public static void RemoveCustomConverter(JsonConverter? converter)
    {
        if (converter == null) return;
        if (!_customConverters.Contains(converter)) return;
        _customConverters.Remove(converter);
    }

    public enum JsonOptionsType
    {
        None,

        // 小驼峰
        CamelCase,

        // 下划线 小写
        UnderLineLower,

        // 下划线 大写
        UnderLineUpper,

        // 中划线 小写
        MiddleLineLower,

        // 中划线 大写
        MiddleLineUpper,
    }

    /// <summary>
    /// 默认
    /// </summary>
    public static JsonSerializerOptions DefaultOptions => GenerateJsonOptions(JsonOptionsType.None);

    /// <summary>
    /// 小驼峰
    /// </summary>
    public static JsonSerializerOptions CamelCaseOptions => GenerateJsonOptions(JsonOptionsType.CamelCase);

    /// <summary>
    /// 下划线 小写
    /// </summary>
    public static JsonSerializerOptions UnderLineLowerOptions => GenerateJsonOptions(JsonOptionsType.UnderLineLower);

    /// <summary>
    /// 下划线 大写
    /// </summary>
    public static JsonSerializerOptions UnderLineUpperOptions => GenerateJsonOptions(JsonOptionsType.UnderLineUpper);

    /// <summary>
    /// 中划线 小写
    /// </summary>
    public static JsonSerializerOptions MiddleLineLowerOptions => GenerateJsonOptions(JsonOptionsType.MiddleLineLower);

    /// <summary>
    /// 中划线 大写
    /// </summary>
    public static JsonSerializerOptions MiddleLineUpperOptions => GenerateJsonOptions(JsonOptionsType.MiddleLineUpper);

    /// <summary>
    /// 生成JsonOptions
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static JsonSerializerOptions GenerateJsonOptions(JsonOptionsType type)
    {
        // 如需改动 Extension.Json.InitJsonSerializerOptions 方法 也许跟随改动
        var options = new JsonSerializerOptions()
        {
            // 忽略空值
            DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
            // 字符串转义 System.Text.Json 默认会对非 ASCII 字符进行转义，会将它们替换为 \uxxxx，其中 xxxx 为字符的 Unicode 代码 关闭转义
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
            // 解决循环引用
            ReferenceHandler = ReferenceHandler.IgnoreCycles,
            // 缩进
            // WriteIndented = true,
            // 允许注释
            ReadCommentHandling = JsonCommentHandling.Skip,
            // 允许尾随逗号
            AllowTrailingCommas = true,
            // 带引号的数字
            NumberHandling = JsonNumberHandling.AllowReadingFromString,
            // 忽略大小写
            PropertyNameCaseInsensitive = true,
            // // 内置转换器
            // Converters =
            // {
            //     // 时间格式化
            //     new DateTimeConverter(),
            //     new DateTimeNullConverter(),
            //     // long转string
            //     new LongToStringConverter(),
            // },
            // TypeInfoResolver = 
        };

        foreach (var converter in _customConverters)
        {
            // 添加自定义转换器
            options.Converters.Add(converter);
        }
        
        // options.Converters.Add(new JsonStringEnumConverter());

        switch (type)
        {
            case JsonOptionsType.CamelCase:
                options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
                break;
            case JsonOptionsType.UnderLineLower:
                options.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower;
                break;
            case JsonOptionsType.UnderLineUpper:
                options.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseUpper;
                break;
            case JsonOptionsType.MiddleLineLower:
                options.PropertyNamingPolicy = JsonNamingPolicy.KebabCaseLower;
                break;
            case JsonOptionsType.MiddleLineUpper:
                options.PropertyNamingPolicy = JsonNamingPolicy.KebabCaseUpper;
                break;
        }

        return options;
    }
}